package cn.agiledata.bank.linkbank.impl.cmbc;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import Union.JnkyServer;
import Union.UnionException;

import cn.agiledata.bank.common.util.IOUtil;
import cn.agiledata.bank.linkbank.exception.LinkBankException;

/**
 * 中国民生银行银行通用方法类
 * 
 * @author jessik
 * 
 */
class CmbcUtils {
    private CmbcUtils() {
    }

    /**
     * 按照民生银行生成数字签名的规则拼凑加密明文
     * 
     * @param values
     *            所有参数
     * @param keys
     *            参与校验的顺序相关的关键字组
     * @return 拼凑好的加密明文
     */
    private static String getScrabbleContent(Map values, String[] keys) {
        String content = "";
        for (int i = 0; i < keys.length; i++) {
            content += values.get(keys[i])
                    + CmbcNetConstant.REQUEST_SEPARATOR;
        }
        if (content.length() > 0) {
            content = content.substring(0, content.length() - 1);
        }
        return content;
    }

    /**
     * 按照民生银行生成数字签名的规则解析明文
     * 
     * @param value
     *            明文
     * @param keys
     *            参与校验的顺序相关的关键字组
     * @return 解析后的明文
     */
    private static Map parseScrabbleContent(String value, String[] keys) {
        Map values = new HashMap();
        String[] tempValues = value.split(CmbcNetConstant.RESPONSE_SEPARATOR);
        for (int i = 0; i < keys.length; i++) {
            if (i < tempValues.length) {
                values.put(keys[i], tempValues[i]);
            } else {
                values.put(keys[i], "");
            }
        }
        return values;
    }

    /**
     * 根据指定公钥文件路径获取公钥内容
     * 
     * @param pulicKeyFilePath
     *            公钥文件路径
     * @return 公钥内容
     * @throws IOException
     */
    private static byte[] getPublicKey(String pulicKeyFilePath)
            throws IOException {
        pulicKeyFilePath = IOUtil.getAbsolutePath(pulicKeyFilePath);
        InputStream in = new FileInputStream(pulicKeyFilePath);
        byte[] fileContent = new byte[in.available()];
        in.read(fileContent);
        in.close();
        return fileContent;
    }

    /**
     * 获取证书文件内容
     * 
     * @param certFilePath
     *            证书文件路径
     * @return 证书文件内容
     * @throws IOException
     */
    private static byte[] getCertContent(String certFilePath)
            throws IOException {
        certFilePath = IOUtil.getAbsolutePath(certFilePath);
        FileInputStream in = new FileInputStream(certFilePath);
        byte[] certContent = new byte[in.available()];
        in.read(certContent);
        in.close();
        return certContent;
    }

    /**
     * 按照民生银行公钥和私钥生成密文
     * 
     * @param values
     *            所有参数
     * @param keys
     *            参与生成的顺序相关的关键字组
     * @param cryptoKey
     *            私钥密码
     * @param publicKeyFilePath
     *            公钥文件路径
     * @param certFilePath
     *            私钥文件路径
     * @return String 密文
     * @throws LinkBankException
     *             若生成过程中出现错误
     */
    public static String getDigitalSign(Map values, String[] keys,
            String cryptoKey, String publicKeyFilePath, String certFilePath)
            throws LinkBankException {
        try {
            byte[] publicKey = getPublicKey(publicKeyFilePath);
            byte[] cert = getCertContent(certFilePath);
            String content = getScrabbleContent(values, keys);
            JnkyServer js = new JnkyServer(publicKey, cert, cryptoKey);
            return js.EnvelopData(content);
        } catch (IOException e) {
            throw LinkBankException.CANNOT_LOAD_CERT;
        } catch (UnionException e) {
            throw LinkBankException.CANNOT_LOAD_CERT;
        } catch (Exception e) {
            throw LinkBankException.getDigitalSignException(e.getMessage());
        }
    }

    /**
     * 按照民生银行私钥解析密文
     * 
     * @param digitalSign
     *            银行返回的密文
     * @param keys
     *            参与生成的顺序相关的关键字组
     * @param cryptoKey
     *            私钥密码
     * @param certFilePath
     *            私钥文件路径
     * @return 明文解析后的Map
     * @throws LinkBankException
     *             若解析过程中出现错误
     */
    public static Map parseDigitalSign(String digitalSign, String[] keys,
            String cryptoKey, String certFilePath) throws LinkBankException {
        try {
            byte[] cert = getCertContent(certFilePath);
            JnkyServer js = new JnkyServer(cert, cryptoKey);
            String jsContent = js.DecryptData(digitalSign);
            return parseScrabbleContent(jsContent, keys);
        } catch (IOException e) {
            throw LinkBankException.CANNOT_LOAD_CERT;
        } catch (UnionException e) {
            throw LinkBankException.CANNOT_LOAD_CERT;
        } catch (Exception e) {
            throw LinkBankException.getDigitalSignException(e.getMessage());
        }
    }
}
